from flask_restful import Resource,reqparse,inputs
from flask import g

from toutiao import db
from toutiao.apps.home.constants import DEFAULT_COMMENT_PER_PAGE_MIN, DEFAULT_COMMENT_PER_PAGE_MAX
from toutiao.utils.decorators import loginrequired
from models.news import Comment, CommentLiking
from cache.comments import ArticleComentCache, CommentCache
from cache.user import UserCommentLikesCache
from cache.staticstic import CommentReplyCountStorage


class CommentsResourve(Resource):
    """
    发表评论
    """
    # method_decorators = [loginrequired]
    method_decorators = {
        "post":[loginrequired]
    }

    def post(self):
        # 接收数据
        parser=reqparse.RequestParser()
        # 添加验证字段
        parser.add_argument('target',location='json',required=True,type=int)
        parser.add_argument('content',location='json',required=True)

        parser.add_argument('art_id',location='json')
        # 验证参数
        args=parser.parse_args()
        # 获取参数
        target=args.get('target')
        content=args.get('content')
        art_id=args.get('art_id')

        user_id=g.user_id

        # 2.添加到数据库
        comment=Comment()
        comment.user_id=user_id
        comment.article_id=target
        comment.content=content

        # 如果有回复评论
        if art_id:
            comment.parent_id = target
            comment.article_id = art_id

            # 添加评论回复数量
            CommentReplyCountStorage.incr(target)

        db.session.add(comment)
        db.session.commit()
        # 3.返回相应
        return {
               "com_id": comment.id,
               "target": target
        },201

    def get(self):
        """
        获取评论列表
        """
        # 接收并校验参数
        # 接收参数
        parser=reqparse.RequestParser()
        # 添加验证字段
        parser.add_argument('type',location='args',required=True)
        parser.add_argument('source',location='args',required=True,type=int)
        parser.add_argument('offset',location='args',type=int)
        parser.add_argument('limit',location='args',type=inputs.int_range(DEFAULT_COMMENT_PER_PAGE_MIN,
                                                                          DEFAULT_COMMENT_PER_PAGE_MAX,
                                                                          'limit'))
        # 验证参数
        args=parser.parse_args()
        # 获取参数
        type=args.get('type')
        source=args.get('source')
        offset=args.get('offset')
        limit=args.get('limit') if args.get('limit') is not None else DEFAULT_COMMENT_PER_PAGE_MIN

        # # 根据type来查询数据库  a是前端写死的
        # if type == 'a':
        #     #查询文章的评论
        #     comments=Comment.query.filter(Comment.article_id==source,
        #                                   Comment.status==Comment.STATUS.APPROVED,
        #                                   Comment.parent_id == None).order_by(Comment.id.desc()).all()
        # else:
        #     # 先这样写防止下面代码报黄
        #     comments = Comment.query.filter(Comment.article_id == source,
        #                                     Comment.status == Comment.STATUS.APPROVED,
        #                                     Comment.parent_id == None).order_by(Comment.id.desc()).all()
        #
        # # 初始化几个变量:计数器,分页数据,总数
        # total_count=len(comments) #评论总数
        # page_comments=[]        # 指定分页的数据
        # end_id=None             # 所有评论的最后一个的创建时间戳
        # last_id=None            # 当前分页的最后一条的创建时间戳
        # item_count=0            # 计数器
        # page_last_comment=None  # 临时变量 来记录分页中最后一条记录的对象
        #
        # # 遍历所有评论
        # for comment in comments:
        #     score = comment.ctime.timestamp()  # 评论创建的时间戳
        #     # 6. 根据指定判断，获取指定的分页数据
        #     # offset 是获取评论的偏移量,个人理解:偏移量就是评论前面的数据
        #
        #     # if (有offset or 没有offset值) and 判断
        #     # 如果品论偏移量不为并且评论时间戳小于评论偏移量and计数器小于等于10,或者
        #     # 评论偏移量为空and 计数器小于等于10
        #     if ((offset is not None and score < offset) or offset is None) and item_count <= DEFAULT_COMMENT_PER_PAGE_MIN:  # 我们就获取第一页的评论数据  一页10条
        #         page_comments.append({
        #             'com_id': comment.id,
        #             'aut_id': comment.user.id,
        #             'aut_name': comment.user.name,
        #             'aut_photo': comment.user.profile_photo,
        #             'pubdate': comment.ctime.strftime('%Y-%m-%d %H:%M:%S'),
        #             'content': comment.content,
        #             'is_top': comment.is_top,
        #             'is_liking': False,
        #             'reply_count': 0
        #         })
        #         item_count += 1
        #         page_last_comment = comment
        #         # 需要将对象转换为字典

        # if total_count > 0:
        #     end_id = comments[-1].ctime.timestamp()
        #     last_id = page_last_comment.ctime.timestamp() if page_last_comment is not None else None

        if type == "a":
            # 获取评论
            total_count,end_id,last_id,page_comments_ids=ArticleComentCache(source).get_page(offset,limit)
            page_comments=[]
            for comment_id in page_comments_ids:
                c = CommentCache(comment_id).get()

                # 判断当前的评论是否被点赞
                is_liking = UserCommentLikesCache(g.user_id).get_comment_liking(comment_id)
                c["is_liking"] = is_liking

                # 获取回复评论
                reply_count = CommentReplyCountStorage.get(comment_id)
                c["reply_count"] = reply_count

                page_comments.append(c)

            # 7. 返回相应
            return {
                "total_count": total_count,
                "end_id": end_id,  # 最后一条评论的id, 前端用于判断是否剩余评论, 无值返回None
                "last_id": last_id,  # 本次请求最后一条评论的id, 作为下次请求的offset, 无值返回None
                "results": page_comments
            }

        else:
            # 获取评论回复
            # 1.查询出所有的评论
            comments = Comment.query.filter(Comment.parent_id == source,
                                            Comment.status == Comment.STATUS.APPROVED).order_by(Comment.id.desc()).all()
            # 2.初始化变量
            #   遍历
            total_count = len(comments)
            end_id = None
            last_id = None
            item_count = 0
            page_last_comment = None
            page_comments = []

            # 3.遍历所有的回复评论
            for comment in comments:
                score = comment.ctime.timestamp()

                # 4.进行分页获取
                if ((offset is not None and score < offset) or offset is None) and item_count <= 10:
                    page_comments.append({
                        'com_id': comment.id,
                        'aut_id': comment.user.id,
                        'aut_name': comment.user.name,
                        'aut_photo': comment.user.profile_photo,
                        'pubdate': comment.ctime.strftime('%Y-%m-%d %H:%M:%S'),
                        'content': comment.content,
                        'is_top': comment.is_top,
                        'is_liking': False,
                        'reply_count': 0
                    })
                    item_count += 1
                    page_last_comment = comment

            if total_count > 0:
                end_id = comments[-1].ctime.timestamp()
                last_id = page_last_comment.ctime.timestamp() if page_last_comment is not None else None

            # 5.返回相应
            return {'total_count': total_count, 'end_id': end_id, 'last_id': last_id, 'results': page_comments}


class CommentLikesResource(Resource):
    """
    评论点赞
    """
    method_decorators = [loginrequired]

    def post(self):

        # 1.接收,验证数据
        parsers = reqparse.RequestParser()
        # 添加验证字段
        parsers.add_argument('target', location='json', required=True, type=int)
        # 验证参数
        args = parsers.parse_args()
        # 获取参数
        target = args.target

        #2. 查询数据库
        cl = CommentLiking.query.filter(CommentLiking.comment_id==target).first()
        # 3. 如果数据不存在则增加
        if cl is None:
            cl = CommentLiking()
            cl.user_id = g.user_id
            cl.comment_id = target
            cl.is_deleted = False
            db.session.add(cl)

        else:
            # 如果不存在,修改标记位
            cl.is_deleted = False
        db.session.commit()

        # 必须在提交之后才能获取到评论的id,所以在commit之后调用add方法将数据缓存到redis
        UserCommentLikesCache(g.user_id).add(target)

        return {'target': target}, 201